#include "insulationCheck.h"
#include "rn8209d.h"
#include "outputCtl.h"
#include "ChargeCtrl.h"
#include "uuPowerProcess.h"
#include "rn8209d.h"
#include "stdio.h"
#include "string.h"
#include "ccsLogicProcess.h"
#include "tcuInterface.h"		//get charger charging step status

//#define RA    750
//#define RB    750.91
//#define RC    750.91
//#define RD    0.91

#define __ISO_DETECTION__ 1
typedef void (*pfunction)(void);

typedef void (*isoCtrlPtrFuncdef)(uint8_t);




typedef struct
{
	uint16_t resistanceX;						//unit 1kr
	uint16_t resistanceY;						//unit 1kr
	uint32_t batVoltage;						//unit 0.1v
	uint32_t isoPgValtage;						//unit 0.1v
	uint32_t isoNgValtage;						//unit 0.1v
	EVSE_IsoStatusE isoStatus;
	EVSE_IsoRunStatusE  Status;	
}insulationDetectionS;


insulationDetectionS insulationDetection[2];



typedef enum
{
	ISO_INIT_STATUS = 0,
	ISO_START_DETECTION,
	ISO_CLOSE_PG_DETECTION,
	ISO_CLOSE_NG_DETECTION,
	ISO_CALCULATE_DETECTION,
	ISO_STOP_DETECTION,	
	IS_RUN_STEP_MAX
}insulationDetectionStepE;


typedef struct 
{
	insulationDetectionStepE isoEventId;						//	eventId run step
	uint8_t entryStatusFlag;									//	
	uint16_t pgWaitTime;										//	pg relay close wait for voltage stability
	uint16_t ngWaitTime;										//  ng relay colose wait for voltage stability
	isoCtrlPtrFuncdef FuncCallback;								//  callback function
	insulationDetectionStepE isoEventIdNext;					//	eventId next statue
	
}isoDetectionDef;



typedef struct
{
    int curState;						//current status
    isoDetectionDef pInsulationDetectionTable[6];		//status table
} IsoDetectionTableS;



IsoDetectionTableS IsoDetectionTable[2];





//uint32_t currTick = HAL_GetTick();

//if (currTick >= systickBak)    // systickBak uint32??
//{
//    if(currTick - systickBak > timeoutMs)
//    {
//        return;
//    }
//}
//else
//{
//    // currTick???
//    if(currTick + (~systickBak) > timeoutMs)
//    {
//        return;
//    }
//}



static void IsoDetectionCalculate(insulationDetectionS *isoPtr)
{
    float viso1;
    float viso2;
	float batVoltage;
    float temp = 0.000000;
    float temp_v1 = 0.000000;
        
	batVoltage = (float)isoPtr->batVoltage / 10;
    viso1 = (float) isoPtr->isoPgValtage / 10000;
    viso2 = (float) isoPtr->isoNgValtage / 10000;
	
	#if defined __ISO_DETECTION__
	printf(" viso1 = %02f, viso2 = %02f \n\n",viso1 ,viso2);
	#endif	
   
    temp =   (float)(batVoltage*RB*RC*RD*(RA+RD)*(viso1-viso2));
	#if defined __ISO_DETECTION__
	printf(" temp = %02f \n",temp );
	#endif	
    temp_v1 = (float)((RA+RD)*(batVoltage*RD*viso2*RB-viso1*viso2*RB*RD -viso1*RA*viso2*RB)+batVoltage*RB*RC*RD*(viso2-viso1));
	#if defined __ISO_DETECTION__
	printf(" temp_v1= %02f \n",temp_v1 );
	#endif
    isoPtr->resistanceY = (float)temp / temp_v1;   //unit kR
 	#if defined __ISO_DETECTION__
	printf(" isoPtr->resistanceY= %d \n",isoPtr->resistanceY );
	#endif   
    temp = ((batVoltage*RB*RC*RD)*(viso2-viso1));
    temp_v1 = (batVoltage*RC*RD*(viso1-viso2)-viso1*viso2*RB*(RA+RD));
    
    isoPtr->resistanceX = temp / temp_v1;  //unit kR
	
	
	if(isoPtr->resistanceY == 0x00)
	{
		isoPtr->resistanceY  = 0xffff;
	}
	 
    if(isoPtr->resistanceX == 0x00)
	{
		isoPtr->resistanceX = 0xffff;
	}
    //when resistance value greater than 100kR   damaged 
    if((isoPtr->resistanceX <  100) || (isoPtr->resistanceY < 500 ))
    {        
        //abnormal error
        isoPtr->isoStatus =  ISO_Fault;
    }    
    //when resistance value greater than 500kR   damaged 
    else if((isoPtr->resistanceX < 100) || (isoPtr->resistanceY < 500))
    {
        //abnormal warnning
        isoPtr->isoStatus = ISO_Warning;
    }
    else
    {
		//normal
        isoPtr->isoStatus = ISO_Valid;
    }
}


int32_t isoGetXresistanceValue(gunIdE gunId)
{
	return insulationDetection[gunId].resistanceX;
}

int32_t isoGetYresistanceValue(gunIdE gunId)
{
	return insulationDetection[gunId].resistanceY;
}

int32_t isoGetInsulationStatu(gunIdE gunId)
{
	return insulationDetection[gunId].isoStatus;
}


int32_t isoGetInsulationStep(gunIdE gunId)
{
	return insulationDetection[gunId].Status;
}


//call insulation detection function.
void isoChargingProcessEntry(gunIdE gunId,int32_t maxVoltage)
{
	//isoCableDetectionVoltageSet(GUNA,400);
	//isoChargDetectionEntry();
	static int32_t systickBak[GUNNUM_MAX];
	static int32_t insulationStep[GUNNUM_MAX] = {0,0};
	
	uint32_t currTick[GUNNUM_MAX];
	
	
	int32_t modulePowerOnTimeoutMs = 10000;
	int32_t relayColseTimeoutMs = 2000;
	
	uint32_t connectorBusVol[GUNNUM_MAX];
	uint32_t connectorbatVol[GUNNUM_MAX];
	uint32_t connectorisoPgVol[GUNNUM_MAX];
	uint32_t connectorisoNgVol[GUNNUM_MAX];
	
//	if(gunId == GUNA)
//	{
//		if(RNL_CCSGetChargingStep(gunId) == CCS_CableChkStep)
//		{
//			//setACContactor(1);  //temp test close ac contact.
//			setModuleCtrl(GUNA,1,POWER_ON|SET_VI,maxVoltage,10);
//			setKeyValueHandle(A_DC_CONTACTOR1_MODULE,1,0,0x00,0x00,NULL);
//		}
//	}
//	else if(gunId == GUNB)
//	{
//		if(RNL_CCSGetChargingStep(gunId) == CCS_CableChkStep)
//		{
//			//setACContactor(1);  //temp test close ac contact.
//			setModuleCtrl(GUNB,1,POWER_ON|SET_VI,maxVoltage,10);
//			setKeyValueHandle(B_DC_CONTACTOR1_MODULE,1,0,0x00,0x00,NULL);
//		}
//	}
	
	if(tcuGetChargerStatsuStep(gunId) == INSULATION_DETECTION)
	{
		//setACContactor(1);	//temp test close ac contact.
		setModuleCtrl(gunId,1,POWER_ON|SET_VI,maxVoltage,10);
		setDCContactor(gunId,1);
	}
	
	if(insulationStep[gunId] == 0)
	{
		systickBak[gunId] = HAL_GetTick();
		insulationStep[gunId] = 1;
		#if defined __ISO_DETECTION__
		printf("step 0 systickBak[gunId] = %d \n",systickBak[gunId] );
		#endif
		insulationDetection[gunId].Status = isoStart;
	}
	else if(insulationStep[gunId] == 1)
	{
		//after 8s get bus voltage.
		currTick[gunId] = HAL_GetTick();
		insulationDetection[gunId].Status = isoRuning;
		#if defined __ISO_DETECTION__
		//printf("step 1 currTick[gunId] = %d  systickBak[gunId] = %d \n",currTick[gunId] , systickBak[gunId]);
		#endif		
		if (currTick[gunId] >= systickBak[gunId])    // systickBak uint32??
		{
			if(currTick[gunId] - systickBak[gunId] > modulePowerOnTimeoutMs)
			{
				//colse pg relay  start insulation detection
				if(gunId == GUNA)
				{
					insulationDetection[gunId].batVoltage = getAgunBatVoltage();
					setKeyValueHandle(A_PG_CTL_MODULE,1,0,0x00,0x00,NULL);					
					#if defined __ISO_DETECTION__
					printf("step 1 A insulationDetection[A].batVoltage = %d \n",insulationDetection[gunId].batVoltage);
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].batVoltage = getBgunBatVoltage();
					setKeyValueHandle(B_PG_CTL_MODULE,1,0,0x00,0x00,NULL);					
					#if defined __ISO_DETECTION__
					printf("step 1 B insulationDetection[A].batVoltage = %d \n",insulationDetection[gunId].batVoltage);
					#endif
				}
				insulationStep[gunId] = 2;
			}
		}
		else
		{
			if(currTick[gunId] + (~systickBak[gunId]) > modulePowerOnTimeoutMs)
			{				
				//colse pg relay  start insulation detection
				if(gunId == GUNA)
				{
					insulationDetection[gunId].batVoltage = getAgunBatVoltage();	
					setKeyValueHandle(A_PG_CTL_MODULE,1,0,0x00,0x00,NULL);
					#if defined __ISO_DETECTION__
					printf("step 2 A insulationDetection[A].batVoltage = %d \n",insulationDetection[gunId].batVoltage);
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].batVoltage= getBgunBatVoltage();
					setKeyValueHandle(B_PG_CTL_MODULE,1,0,0x00,0x00,NULL);
					#if defined __ISO_DETECTION__
					printf("step 2 B insulationDetection[A].batVoltage = %d \n",insulationDetection[gunId].batVoltage);
					#endif
				}
				insulationStep[gunId] = 2;
			}
		}
	}
	else if(insulationStep[gunId] == 2)
	{
		//after 9s  get pg iso voltage.
		currTick[gunId] = HAL_GetTick();
		
		#if defined __ISO_DETECTION__
		//printf("step 2 currTick[gunId] = %d  systickBak[gunId] = %d\n",currTick[gunId] , systickBak[gunId] );
		#endif
		if (currTick[gunId] >= systickBak[gunId])			
		{
			if(currTick[gunId] - systickBak[gunId] > (modulePowerOnTimeoutMs + relayColseTimeoutMs))
			{
				if(gunId == GUNA)
				{
					insulationDetection[gunId].isoPgValtage  = getAgunBatIsoVoltage();
					//close ng relay  A_NG_CTL_MODULE
					setKeyValueHandle(A_NG_CTL_MODULE,1,0,0x00,0x00,NULL); 
					#if defined __ISO_DETECTION__
					printf("step 2 A insulationDetection[A].isoPgValtage = %d \n",insulationDetection[gunId].isoPgValtage);
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].isoPgValtage = getBgunBatIsoVoltage();
					//close ng relay 
					setKeyValueHandle(B_NG_CTL_MODULE,1,0,0x00,0x00,NULL);
					#if defined __ISO_DETECTION__
					printf("step 2 B insulationDetection[A].isoPgValtage = %d \n",insulationDetection[gunId].isoPgValtage);
					#endif
				}
				insulationStep[gunId] = 3;	
			}
		}
		else
		{
			if(currTick[gunId] + (~systickBak[gunId]) > (modulePowerOnTimeoutMs + relayColseTimeoutMs))
			{
				//get connector A and B insulation voltage . 
				if(gunId == GUNA)
				{
					insulationDetection[gunId].isoPgValtage = getAgunBatIsoVoltage();
					//close ng relay 
					setKeyValueHandle(A_NG_CTL_MODULE,1,0,0x00,0x00,NULL);
					#if defined __ISO_DETECTION__
					printf("step 2 A insulationDetection[A].isoPgValtage = %d \n",insulationDetection[gunId].isoPgValtage);
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].isoPgValtage = getBgunBatIsoVoltage();
					//close ng relay 
					setKeyValueHandle(B_NG_CTL_MODULE,1,0,0x00,0x00,NULL);
					#if defined __ISO_DETECTION__
					printf("step 2 B insulationDetection[A].isoPgValtage = %d \n",insulationDetection[gunId].isoPgValtage);
					#endif
				}
				insulationStep[gunId] = 3;
			}
		}
	}
	else if(insulationStep[gunId] == 3)
	{
		//after 10s  get pg iso voltage.
		currTick[gunId] = HAL_GetTick();
		
		#if defined __ISO_DETECTION__
		//printf("step 3 currTick[gunId] = %d  systickBak[gunId] = %d\n",currTick[gunId] , systickBak[gunId] );
		#endif
		if (currTick[gunId] >= systickBak[gunId])			
		{
			if(currTick[gunId] - systickBak[gunId] > (modulePowerOnTimeoutMs + relayColseTimeoutMs + relayColseTimeoutMs))
			{
				if(gunId == GUNA)
				{
					insulationDetection[gunId].isoNgValtage = getAgunBatIsoVoltage();
					#if defined __ISO_DETECTION__
					printf("step 3 A insulationDetection[gunId].isoNgValtage  = %d \n",insulationDetection[gunId].isoNgValtage );
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].isoNgValtage = getBgunBatIsoVoltage();
					#if defined __ISO_DETECTION__
					printf("step 3 B insulationDetection[gunId].isoNgValtage  = %d \n",insulationDetection[gunId].isoNgValtage );
					#endif
				}
				insulationStep[gunId] = 4;
			}
		}
		else
		{
			if(currTick[gunId] + (~systickBak[gunId]) > (modulePowerOnTimeoutMs + relayColseTimeoutMs + relayColseTimeoutMs))
			{
				if(gunId == GUNA)
				{
					insulationDetection[gunId].isoNgValtage = getAgunBatIsoVoltage();
					#if defined __ISO_DETECTION__
					printf("step 3 A insulationDetection[gunId].isoNgValtage  = %d \n",insulationDetection[gunId].isoNgValtage );
					#endif
				}
				else if(gunId == GUNB)
				{
					insulationDetection[gunId].isoNgValtage = getBgunBatIsoVoltage();
					#if defined __ISO_DETECTION__
					printf("step 3 B insulationDetection[gunId].isoNgValtage  = %d \n",insulationDetection[gunId].isoNgValtage );
					#endif
				}
				insulationStep[gunId] = 4;
			}
		}
	}
	else if(insulationStep[gunId] == 4)
	{
		if(gunId == GUNA)
		{
			if(RNL_CCSGetChargingStep(gunId) == CCS_CableChkStep)
			if(tcuGetChargerStatsuStep(gunId) == INSULATION_DETECTION)
			{
				setModuleCtrl(GUNA,1,POWER_DOWN,0,0);
//				setKeyValueHandle(A_DC_CONTACTOR1_MODULE,0,0,0x00,0x00,NULL);
				setDCContactor(gunId,0);
			}
			setKeyValueHandle(A_NG_CTL_MODULE,0,0,0x00,0x00,NULL);
		
			IsoDetectionCalculate(&insulationDetection[GUNA]);
			#if defined __ISO_DETECTION__
			
			printf("step 4  VBAT = %d  VISO1 = %d   VISO2  = %d\n",insulationDetection[gunId].batVoltage, insulationDetection[gunId].isoPgValtage , insulationDetection[gunId].isoNgValtage);
			printf("step 4 A X resistance  = %d  Y resistance = %d iso status  %d ,run status %d\n",insulationDetection[GUNA].resistanceX,insulationDetection[GUNA].resistanceY,
			insulationDetection[GUNA].isoStatus,insulationDetection[GUNA].Status);
			#endif			
		}
		else if(gunId == GUNB)
		{
//			if(RNL_CCSGetChargingStep(gunId) == CCS_CableChkStep)			
			if(tcuGetChargerStatsuStep(gunId) == INSULATION_DETECTION)
			{
				setModuleCtrl(GUNB,1,POWER_DOWN,0,0);
//				setKeyValueHandle(B_DC_CONTACTOR1_MODULE,0,0,0x00,0x00,NULL);	
				setDCContactor(gunId,0);
			}
			setKeyValueHandle(B_NG_CTL_MODULE,0,0,0x00,0x00,NULL);
			IsoDetectionCalculate(&insulationDetection[GUNB]);	
			#if defined __ISO_DETECTION__
			printf("step 4  VBAT = %d  VISO1 = %d   VISO2  = %d\n",insulationDetection[gunId].batVoltage, insulationDetection[gunId].isoPgValtage , insulationDetection[gunId].isoNgValtage);
			printf("step 4 B X resistance  = %d  Y resistance = %d iso status  %d ,run status %d\n",insulationDetection[GUNB].resistanceX,insulationDetection[GUNB].resistanceY,
			insulationDetection[GUNB].isoStatus,insulationDetection[GUNB].Status);
			#endif
		}
		insulationDetection[gunId].Status = isoStop;		
		insulationStep[gunId] = 0;
	}
}


